package com.zb.internetSpider.utils;




/**
 * 
 * 字符串工具函数
 * 新版本的说明，多个新版本依次换行说明
 * @author zb
 * @date : 2017年11月16日 下午5:04:01
 * @version V1.0
 * @since JDK 1.8
 */
public class StringUtil {
	/**
	 * 
	 * 字符串是否为空对象或空字符串
	 * 多版本请换行描述
	 * @param str
	 * @return boolean
	 * @author : zb
	 * @date : 2017年11月16日 下午5:04:23
	 * @version V1.0
	 */
	public static boolean isEmptyOrNull(String str) {
		if(str == null || str.equals("")) 
			return true ;
		return false ;
	}
	/**
	 * 
	 * 字符串是否不为空对象或空字符串
	 * 多版本请换行描述
	 * @param str
	 * @return boolean
	 * @author : zb
	 * @date : 2017年11月16日 下午5:05:20
	 * @version V1.0
	 */
	public static boolean isNotEmpty(String str) {
		if(str == null || str.equals("")) 
			return false ;
		return true ;
	}
	
	
    /* 判断是否是服务器请求*/
//    public static Boolean  isUrl(String url) {
//    	try {
//    		 return !Pattern.matches(RegexConstants.ISURL, url);
//		} catch (Exception e) {
//			// TODO: handle exception			
//			return false;
//		}
//    }

    /* 取url中最后C子字符串及之后的字符串*/
    public static String getSuffix(String url, String c) throws StringException,NullPointerException {    			
                if(url.lastIndexOf(c)==-1){                	
                	 throw new StringException(url+"字符串中未找到"+c+"字符串");
                }
                else   
                     return url.substring(url.lastIndexOf(c), url.length());
    }
    /**
     * 
     * 判断是否是properties文件
     * 多版本请换行描述
     * @param url
     * @return Boolean
     * @author : zb
     * @date : 2017年8月26日 下午8:51:17
     * @version V1.0
     * @throws StringException 
     */
    public static boolean isProperties(String name){
    	try {
    		return getSuffix(name, ".").equals(".properties");		
		}catch(Exception e){	
			e.printStackTrace();
			return false;
		}
    }
    /**
     * 
     * 判断第一个字符串最后面是否含有第二个字符串
     * 多版本请换行描述
     * @param url
     * @return Boolean
     * @author : zb
     * @date : 2017年8月27日 下午7:50:37
     * @version V1.0
     */
    public static boolean isSome(String url ,String target){
    	try {
			getSuffix(url, target);
			return true;
		} catch (NullPointerException e) {
			// TODO Auto-generated catch block
			
			return false;
		} catch (StringException e) {
			// TODO Auto-generated catch block
			
			return false;
		}
    }
    /**
     * 
     * 将Map的值转为字符串
     * 多版本请换行描述
     * @param object
     * @return String
     * @author : zb
     * @date : 2017年9月10日 下午5:09:38
     * @version V1.0
     */
    public static String toString(Object object){
    	return null==object?"":object.toString();
    }
    /**
     * 
     * 字符串转布尔
     * 多版本请换行描述
     * @param str
     * @return boolean
     * @author : zb
     * @date : 2017年11月17日 下午4:36:50
     * @version V1.0
     */
    public static boolean toBoolean(String str){
    	return Boolean.valueOf(str);
    }
    
	/**
     * 通配符算法。 可以匹配"*"和"?"
     * 如a*b?d可以匹配aAAAbcd
     * @param pattern 匹配表达式
     * @param str 匹配的字符串
     * @return
     */	
	public static boolean match(String pattern, String str) {
	        if (pattern == null || str == null)
	            return false;
	 
	        boolean result = false;
	        char c; // 当前要匹配的字符串
	        boolean beforeStar = false; // 是否遇到通配符*
	        int back_i = 0;// 回溯,当遇到通配符时,匹配不成功则回溯
	        int back_j = 0;
	        int i, j;
	        for (i = 0, j = 0; i < str.length();) {
	            if (pattern.length() <= j) {
	                if (back_i != 0) {// 有通配符,但是匹配未成功,回溯
	                    beforeStar = true;
	                    i = back_i;
	                    j = back_j;
	                    back_i = 0;
	                    back_j = 0;
	                    continue;
	                }
	                break;
	            }
	 
	            if ((c = pattern.charAt(j)) == '*') {
	                if (j == pattern.length() - 1) {// 通配符已经在末尾,返回true
	                    result = true;
	                    break;
	                }
	                beforeStar = true;
	                j++;
	                continue;
	            }
	 
	            if (beforeStar) {
	                if (str.charAt(i) == c) {
	                    beforeStar = false;
	                    back_i = i + 1;
	                    back_j = j;
	                    j++;
	                }
	            } else {
	                if (c != '?' && c != str.charAt(i)) {
	                    result = false;
	                    if (back_i != 0) {// 有通配符,但是匹配未成功,回溯
	                        beforeStar = true;
	                        i = back_i;
	                        j = back_j;
	                        back_i = 0;
	                        back_j = 0;
	                        continue;
	                    }
	                    break;
	                }
	                j++;
	            }
	            i++;
	        }
	 
	        if (i == str.length() && j == pattern.length())// 全部遍历完毕
	            result = true;
	        return result;
	    }
	
	/**
	 * 
	 * 超链接通配实现算法  
	 * 说明： ？表示任意一个字符， * 表示任意一级路径， ** 表示任意多级路径
	 * 规则：*的下级路径不允许是*，**; **的下级路径不允许是*，**.  ?在同一路径下可出现多次 
	 * 用法： a/?g/b  可以匹配 a/cg/b 或 a/yg/b
	 *      a/ ** /f 可以匹配 a/d/f/g/h/f  或a/sdfdsd/dfdf/f
	 *      a/ * /f  可以匹配 a/ ghfjkhf/f
	 * 多版本请换行描述
	 * @param url 超链接
	 * @param pattern  通配表达式
	 * @return boolean 
	 * @author : zb
	 * @date : 2017年12月25日 下午12:08:07
	 * @version V1.0
	 */
	public static boolean matchUrl(String url, String pattern) {
		if (pattern == null || url == null)
            return false;
		String[] patternArray = pattern.split("/");
		String[] urlArray = url.split("/");	
		
		int i = patternArray.length;  // 通配表达式的级数
		int j = urlArray.length;  // 超链接的级数
		
	    //  由通配的多级**通配符可知，超链接的级数肯定不会小于通配表达式的级数，所以出现小于的情况时，就不用匹配了，直接返回false
		if(j<i)
			return false;
		
		
		int i_index = 1; // 通配表达式当前的活跃级数
		int j_index = 1; // 超链接当前的活跃级数
		
		boolean beforeStar = false; // 是否遇到通配符**
		 
		// 当通配表达式当前活跃级数小于等于通配表达式的级数时， 证明通配没有完成，继续匹配
		while(i_index<= i) {
			
			// 当超链接当前活跃级数小于等于超链接的级数时，证明通配可以继续进行
			if(j_index <= j) {
				
				// 当遇到多级通配符**
				if(patternArray[i_index-1].equals("**")) {					
					// 遇到通配符**
					beforeStar = true;
					// 如果**是通配表达式的最后一级，证明通配是成功的，超链接的下级匹配路径可以完成
					if(i_index == i){
						beforeStar = false;
						return true;
					}					
					// 如果**是通配表达式的下级路径是*或**,则证明匹配规则错误，不在进行匹配，返回false;
					if(patternArray[i_index].equals("*") || patternArray[i_index].equals("**")){
						beforeStar = false;
						return false;
					}
					
					// 以上情况都不存在，对通配表达式**这级之后的表达式进行匹配，并将通配表达式当前的活跃级数+1
					String curr = patternArray[i_index++];				
					/* 从超链接当前活跃级数向下匹配通配表达式当前的活跃级数, 直到匹配到或超链接当前活跃级数大于超链接的级数时，
					 * 当匹配到的时候，退出通配** 的状态
					 */							
					/*
					 * 当curr里含有？通配符的时候 
					 */
					if(curr.contains("?")) {						
						while(beforeStar && j_index<=j) {
							// 因为？好是单个字符的匹配，所以若想匹配通过，则通配表达式的长度和超链接的长度是相同的
							if(curr.length() == urlArray[j_index-1].length()) {
								// 是否通过匹配
								boolean ok = true;
								for(int x=0;x<curr.length();x++){
									char index = curr.charAt(x);
									if(index == '?')
										continue;
									else if(curr.charAt(x) == urlArray[j_index-1].charAt(x))
										continue;
									else {
										ok=false;
										break;
									}
								}
								if(ok){
									beforeStar = false;
									i_index++;
								}
							}
							j_index++;						
						}
						
					}else {						
						while(beforeStar && j_index<=j) {							
							if(urlArray[j_index-1].equals(curr)) {
								beforeStar = false;
								i_index++;									
							}
							j_index++;									
						}						
					}
					// 当超链接都匹配过，但没有找到可以匹配的数据时
					if(beforeStar)
						return false;					
					// 找到匹配数据了，进行 下一轮通配表达式匹配
					continue;	
				}
				
				
		//当遇到*单级路径通配的时候
				if(patternArray[i_index-1].equals("*")) {
					// 如果*是通配表达式的最后一级时，判断超链接的当前的活跃级数是否等于超链接的级数，若相等则匹配成功，否则失败
					if(i_index == i){
						if(j_index == j)
							return true;
						else
							return false;
					}		
					// 如果*的通配表达式的下级路径是*或**,则证明匹配规则错误，不在进行匹配，返回false;
					if(patternArray[i_index].equals("*") || patternArray[i_index].equals("**")){
						beforeStar = false;
						return false;
					}				
					
					// 以上情况不存在的时候， 进行下级匹配
					j_index++;
					i_index++;	
				}
		 // ** 和 * 通配符都不在的时候
				// 当存在？通配符时
				if(patternArray[i_index-1].contains("?")) {						
					// 因为？好是单个字符的匹配，所以若想匹配通过，则通配表达式的长度和超链接的长度是相同的
					if(patternArray[i_index-1].length() == urlArray[j_index-1].length()) {
						// 是否通过匹配
						boolean ok = true;
						
						for(int x=0;x<patternArray[i_index-1].length();x++){
							char index = patternArray[i_index-1].charAt(x);
							if(index == '?')
								continue;
							else if(patternArray[i_index-1].charAt(x) == urlArray[j_index-1].charAt(x))
								continue;
							else {
								ok=false;
								break;
							}
						}					
						if(ok){
							i_index++;
							j_index++;
							continue;
						}
					}
					return false;						
					
				}else {					
					if(urlArray[j_index-1].equals(patternArray[i_index-1])) {
						i_index++;
						j_index++;
						continue;
					}else 
						return false;				
				}		
			}else {
				// 当超链接当前活跃级数大于超链接的级数时，说明通配还没有匹配结束但是超链接已经匹配完成了，后续通配无法进行，返回false,匹配失败
				return false;
			}	
		}
		//  是否完成匹配	
		return (i==i_index-1 && j==j_index-1);
  }

	
	
	
	
	
	public static void main(String[] args) {
		String url = "auth/delete/auth";
		String pattern ="auth/**/???h";
		
		System.out.println(matchUrl(url, pattern));
	}
	
}
